package me.luraframework.gateway.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import lombok.AllArgsConstructor;
import org.springdoc.core.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.SwaggerUiConfigParameters;
import org.springdoc.core.SwaggerUiConfigProperties;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.gateway.event.RefreshRoutesResultEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static me.luraframework.gateway.module.route.GwApi.ROUTE_METADATA_SWAGGER_URL;

/**
 * @ description: SwaggerConfig
 * @ author: Liu Ran
 * @ data: 6/2/23 16:41
 */
@Configuration
@AllArgsConstructor
public class SwaggerConfig implements ApplicationListener<ApplicationReadyEvent> {

    private final SwaggerUiConfigProperties configProperties;
    private final RouteDefinitionLocator locator;

    private AbstractSwaggerUiConfigProperties.SwaggerUrl currentSwagger() {
        return new AbstractSwaggerUiConfigProperties.SwaggerUrl(
                "gateway", "/v3/api-docs", "gateway"
        );
    }

    @EventListener(RefreshRoutesResultEvent.class)
    public void refreshRoutesResultEvent() {
        Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> urls = new HashSet<>();

        locator.getRouteDefinitions()
                .doOnNext(routeDefinition -> {
                    urls.add(currentSwagger());
                    String apiDocs = (String) routeDefinition.getMetadata().get(ROUTE_METADATA_SWAGGER_URL);
                    if (Objects.nonNull(apiDocs)) {
                        String name = routeDefinition.getId();
                        urls.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl(name, name + "/" + apiDocs, name));
                    }
                })
                .doOnComplete(() -> configProperties.setUrls(urls)).subscribe();
    }


    @Bean
    public OpenAPI customOpenApi() {
        return new OpenAPI().info(new Info().title("springdoc gateway API")
                .description("springdoc gateway API")
                .version("v1.0.0")
                .contact(new Contact()
                        .name("姓名")
                        .email("邮箱")));
    }


    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        refreshRoutesResultEvent();
    }
}
